<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
    <title>Javascript Review</title>
    <style>
        pre{
            display: block;
            width:100%;
            background: rgb(225, 193, 189);
        }
        h1,h2,h3,h4,h5,h6{
            text-transform: capitalize
        }
    </style>
</head>
<body class="container">
    <h1>Javascript Guide</h1>
    <h2>introduction</h2>
    <ul>
        <li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide">overview</a></li>
        <li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference">Detailed Reference</a></li>
    </ul>
    <p>javascripti is a cross-platform, object-orientated scripting language used to make webpages interactive</p>
    <p>JavaScript contains a standard library of objects, such as Array, Date, and Math, and a core set of 
        language elements such as operators, control structures, and statements. Core JavaScript can be extended 
        for a variety of purposes by supplementing it with additional objects: for example:</p>
    <ul>
        <li><strong>Client-side JavaScript</strong> extends the core language by supplying objects to control a browser and its 
            Document Object Model (DOM). For example, client-side extensions allow an application to place elements 
            on an HTML form and respond to user events such as mouse clicks, form input, and page navigation.</li>
        <li><strong>Server-side JavaScript</strong>extends the core language by supplying objects relevant to running JavaScript 
            on a server. For example, server-side extensions allow an application to communicate with a database, 
            provide continuity of information from one invocation to another of the application, or perform file 
            manipulations on a server</li>
    </ul>
    <h2>Grammar and types</h2>
    <h3>Basics and comments</h3>
    <p>JavaScript is case-sensitive</p>
    <h3>declaration</h3>
    <p>there are 3 types of declaration:</p>
    <dl>
        <dt>var</dt>
        <dd>Declares a variable, optionally initializing it to a value, otherwise specified to the value of undefined</dd>
        <dt>let</dt>
        <dd>Declares a block-scoped, local variable, optionally initializing it to a value, otherwise specified to the value of undefined</dd>
        <dt>const</dt>
        <dd>Declares a block-scoped, read-only named constant, <span class="text-danger">must be initialized</span>.</dd>
    </dl>
    <h4>variable</h4>
    <p>AKA:identifier, start with a letter, _ or $</p>
    <h5>variable scope</h5>
    <p>when you declare a variale outside of <span class="text-danger">any function</span>, it is called a global variable, otherwise it's a local variable</p>
    <h5>variable hoisting</h5>
    <p>we can refer to a variable declared later without getting an exception， this is called hoisting</p>
    <p>varibales are hoisted or lifted to the top of function of a statement, 但是在ES6中，使用let关键字不会有hoisting</p> 
    <pre>
            var myvar = 'my value';
 
            (function() {
              console.log(myvar); // undefined
              var myvar = 'local value';
            })();
    </pre>
    <p>为什么是undefined？主要是两个原因，一个是因为使用了同名变量，另一个是hoisting，所以上面的例子等同于</p>
    <pre>
            var myvar = 'my value';
            (function() {
              var myvar;
              console.log(myvar); // undefined
              myvar = 'local value';
            })();
    </pre>
    <p>在一个function内，variable 会被提前，所以才会出现undefined，如果删掉方法内的myvar 这样也不会报错，因为直接打印的是function外的值</p>
    <h5>funciton hoisting</h5>
    <p>For functions, only the function declaration gets hoisted to the top and not the function expression.查看function部分
        了解什么是definition，什么是expression
    </p>
    <p>只有函数声明被提升，但是函数表达式不能提升</p>
    <ul class="row">
        <li>函数声明: <pre>foo(); // "bar"

        function foo() {
            console.log('bar');
        }</pre></li>
        <li>函数表达式: <pre>
                baz(); // TypeError: baz is not a function

        var baz = function() {
            console.log('bar2');
        };
        </pre></li>
    </ul>

    <h3>Data structures and types</h3>
    
    <div class="d-flex">
        <ul>
            <caption>there are 8 data types</caption>
            <li>Boolean</li>
            <li>null, and it's different from Null, or NULL</li>
            <li>undefined</li>
            <li>Number,such as 42, or 3.1415</li>
            <li>BigInt, an integer with arbitrary precision, such as 901543154n</li>
            <li>String</li>
            <li>Symbol, whose data instances are unique and immutable</li>
            <li>Object</li>
        </ul>
        <ul>
            <caption>there are several literals</caption>
            <li>Array Literals</li>
            <li>Bool Literals</li>
            <li>Floating-point Literals</li>
            <li>Integers</li>
            <li>Object Literals</li>
            <li>RegExp Literals</li>
            <li>String Literals</li>
        </ul>
    </div>
    <h2>Control flow and error handling</h2>
    <p>Javascript support a set of statements(语句). statements are seperated with semicolons (;) </p>
    <ol>
        <li>
            <caption>Block statement</caption>
            <p>it's used to group statement. The block is delimited by a pair of curly bracket.</p>
            <p>They are commonly used with control flow statements (e.g. if else, while)</p>
            <p>在ECMAscript 2015(ES6)之前，没有block scope(块级作用域)的概念，换句话说 大括号包含的语句并不能定义一个作用域,
            在ES6之后，let和const的变量声明是块级作用域的(black scoped)
            </p>
        </li>
        <li>
            <caption>conditional statement(if else)</caption>
            <p>the condition evaluates to false, when the value is 0,-0,null,false,NaN,undefined. Otherwise, the condition is true</p>
            <p>notice! condition是true 和 boolean类型的false是不一样的</p>
        </li>
        <li>
            <caption>conditional statement(switch)</caption>
            <pre>
switch (fruittype) {
    case 'Oranges':
        console.log('Oranges are $0.59 a pound.');
        break;
    case 'Apples':
        console.log('Apples are $0.32 a pound.');
        break;
    }
            </pre>
        </li>
        <li>
            <caption>exception handling statements(throw)</caption>
            <p>used to throw and exception, usage: throw  expression</p>
            <p>throw "Error2"; throw 42</p>
        </li>
        <li>
            <caption>exception handling statements(try..catch)</caption>
            <p>used to specfiy responses when an exception is thrown</p>
            <p>The finally block executes whether or not an exception is 
                thrown. If an exception is thrown, the statements in the finally block execute 
                even if no catch block handles the exception.</p>
        </li>
        <li></li>
    </ol>
    <h2>Loops and iteration</h2>
    <p>there are various situations that are more easily served by one type of loop over ther others</p>
    <ol>
        <li>
            <caption>for statement</caption>
            <p>无限循环一直到条件判定失败</p>
            <pre>
for ([initialExpression]; [condition]; [incrementExpression])
statement
            </pre>
        </li>
        <li>
            <caption>do while statement</caption>
            <p>进行条件判定，至少执行一次，然后无限循环到条件失败</p>
            <pre>
do
statement
while (condition);
            </pre>
        </li>
        <li>
            <caption>while statement</caption>
            <p>执行循环体，无限循环到条件失败</p>
            <pre>
while (condition)
statement
            </pre>
        </li>
        <li>
            <caption>labeled statement</caption>
            <p>It provides a statement with an identifier that you can refer to elsewhere in your program</p>
            <p>给一个statement命名，一般是用于iteration statement, 可以在其他位置进行调用</p>
            <pre>
label :
statement     

markLoop:
    while (theMark == true) {
        doSomething();
    }
            </pre>
        </li>
        <li>
            <caption>break statement</caption>
            <p>used to teminate a loop, switch or inconjunction with a labeled statement</p>
            <p>use break without a label, terminates the innermost(最里面的) enclosing while, do while, for or switch </p>
            <p>use break with a label, it teminates the specified labeled statement</p>
            <p>useage: break [label]</p>
        </li>
        <li>
            <caption>continue statement</caption>
            <p>used to restart a while, do-while, for or labeled statement</p>
        </li>
        <li>
            <caption>for in statement</caption>
            <p>The for in statement iterates a specified variables over all the enumerable properties of an object</p>
            <p>用于遍历一个object的属性，且属性是可数属性, 可知对象的所有属性和值</p>
            <p class="warning">for-in也可以用来遍历一个list但是如下图所示，key针对一般array返回的是index值，针对object返回
                的是属性名，返回的都是不是value，返回value的话还需要用key做下标，所以不如直接使用for-of方法
            </p>
            <pre>
for (variable in object) {
    statements
    }

var obj = {
    name: 'test',
    color: 'red',
    day: 'sunday',
    number: 5
}
for (var key in obj) {
    console.log(key)
    console.log(obj[key])
}
            </pre>
        </li>
        <li>
            <caption>for of statement</caption>
            <p class="text-warning">It creates a loop iterating over iterable objects(including Array, Map, Set, arguments object and so on)</p>
            <p>for in 和 for of之间的区别，for-in取到index，for-of可以取到内容</p>
            <ul>
                <li>for..of适用遍历数/数组对象/字符串/map/set等拥有迭代器对象的集合.但是不能遍历对象,因为没有迭代器对象.与forEach()不同的是，它可以正确响应break、continue和return语句</li>
                <li>for-of循环不支持普通对象，但如果你想迭代一个对象的属性，你可以用for-in循环（这也是它的本职工作）或内建的Object.keys()方法</li>
            </ul>
            <pre>
                var arr = [3, 5, 7];
arr.foo = 'hello';
// for-in 把foo属性也计算在内，但是length始终是3，所以有了for-of解决这个问题
for (var i in arr) {
   console.log(i); // logs "0", "1", "2", "foo"
}
// for-of 只遍历本身的元素
for (var i of arr) {
   console.log(i); // logs 3, 5, 7
}
            </pre>
        </li>
    </ol>

    <h2>Functions</h2>
    <h3>Defining functions</h3>
    <p>function definition is also called function declaration or function statement</p>
    <pre>
function square(number) {
    return number * number;
    }
    </pre>
    <h3>Function expression</h3>
    <p>it's another to create a function</p>
    <p>such as var square = function(number) { return number * number; };</p>
    <p>function expression is convenient when passing a function as an argument to another function</p>
    <p class="text-waring">a method is a function that is a property of an object</p>
    <h3>calling functions</h3>
    <pre>
console.log(square); // square is hoisted with an initial value undefined.
console.log(square(5)); // Uncaught TypeError: square is not a function
var square = function(n) { 
  return n * n; 
}
    </pre>
    <p>这是因为: function hoisting only works with function declaration and not with function expression.</p>
    <h3>function scope</h3>
    <p> a function can access all variables and functions defined inside the scope in which it is defined</p>
    <p>A  function defined inside another function can also access all variables defined in its parent function 
        and any other variable to which the parent function has access.</p>
    <h3>scope and function stack</h3>
    <h4>recursion</h4>
    <p>A function can call itself, there are three ways</p>
    <ul>
        <li>the function's name</li>
        <li>auguments.callee</li>
        <li>an in-scope varibale that refers to the function</li>
    </ul>
    <pre>
var foo = function bar() {
    // statements go here
    };
    </pre>
    <p>they are equivalent</p>
    <ul>
        <li>bar()</li>
        <li>arguments.callee()</li>
        <li>foo()</li>
    </ul>
    <p>recursion和loop很像，都是在进行重复操作，都需要一个condition</p>
    <p>loop可以转化成recursion，recursion也可以转化成loop，但是有时候逻辑会比较麻烦</p>
    <h4>nested functions and closures</h4>
    <ul>
        <li>The inner function can be accessed only from statements in the outer function.</li>
        <li>The inner function forms a closure: the inner function can use the arguments and 
            variables of the outer function, while the outer function cannot use the arguments and variables of the inner function.</li>
    </ul>
    <h3>closures</h3>
    <p>Closures are one of the most powerful features of JavaScript. JavaScript allows for the nesting of functions and grants the inner function 
        full access to all the variables and functions defined inside the outer function (and all other variables and functions that the outer function 
        has access to). However, the outer function does not have access to the variables and functions defined inside the inner function. This provides a sort
         of encapsulation for the variables of the inner function. Also, since the inner function has access to the scope of the outer function, the variables and 
         functions defined in the outer function will live longer than the duration of the outer function execution, if the inner function manages to survive 
         beyond the life of the outer function. <span class="text-danger">A closure is created when the inner function is somehow made available to any scope outside the outer 
        function. 当外部函数将内部函数作为return的返回值的时候，就会形成一个闭包</span> </p>
    <h3>Using the arguments object</h3>
    <p>每个函数都有一个arguments变量,it's an arrry-like variable，but not same as Array, because it has numbered index and a length property
        but it doesn't have all of array manipulation method
    </p>
    <pre>
function myConcat(separator) {
    var result = ''; // initialize list
    var i;
    // iterate through arguments
    for (i = 1; i < arguments.length; i++) {
        result += arguments[i] + separator; 
    }
    return result;
    }
    </pre>
    <h3>Function parameters</h3>
    <p>从ES6开始以来，我们有了两种新增的parameters</p>
    <h4>default parameters</h4>
    <p>一般来说，function的parameter的默认值是undefined，但是有些情况下，需要设置默认值，用法如下</p>
    <p>function multiply(a,b=2){}</p>
    <h4>rest parameter</h4>
    <p>The rest parameter syntax allows us to represent an indefinite number of arguments as an array.</p>
    <pre>
function multiply(multiplier, ...theArgs) {
    return theArgs.map(x => multiplier * x);
    }
    var arr = multiply(2, 1, 2, 3);
    console.log(arr); // [2, 4, 6]
    </pre>
    <h3>Arraw Function</h3>
    <p>arraw function的出现只是简化了function expression但是没有取代function declaration</p>
    <p>it doesn't have its own <code>this, arguments, super</code> or <code>new.target</code></p>
    <ul>
        <p>two factors affect the introduction of arrow function</p>
        <li>
            short functions: in functional patterns/programming, shorter functions are welcome.
        </li>
        <li>
            non binding of this:
            <table class="table">
                <thead>
                    <tr>
                        <th scope="col">ES5 function</th>
                        <th scope="col">ES5 alternative 1</th>
                    </tr>
                </thead>
                <tbody>
                    <tr>
                    <td>
                        <pre>
function Person() {
    // The Person() constructor defines `this` as itself.
    this.age = 0;
    
    setInterval(function growUp() {
        // In nonstrict mode, the growUp() function defines `this` 
        // as the global object, which is different from the `this`
        // defined by the Person() constructor.
        this.age++;
    }, 1000);
    }
    
    var p = new Person();
                        </pre>
                    </td>
                    <td>
                        <pre>
function Person() {
    var self = this; // Some choose `that` instead of `self`. 
                        // Choose one and be consistent.
    self.age = 0;
    
    setInterval(function growUp() {
        // The callback refers to the `self` variable of which
        // the value is the expected object.
        self.age++;
    }, 1000);
    }
                        </pre>
                    </td>
                    </tr>
                    <tr>
                        <th scope="col">ES5 alternative 2</th>
                        <th scope="col">ES6 arrow function</th>
                    </tr>
                    <tr>
                        <td>
                                <pre>
function Person() {
    // The Person() constructor defines `this` as itself.
    this.age = 0;
    
    function growUp() {
        // In nonstrict mode, the growUp() function defines `this` 
        // as the global object, which is different from the `this`
        // defined by the Person() constructor.
        this.age++;
    }
    growUp.bind(this)()
    }
    
    var p = new Person();
                                </pre>
                        </td>
                            <td>
                                <pre>
function Person() {
    this.age = 0;
    
    setInterval(() => {
        this.age++; // |this| properly refers to the person object
    }, 1000);
    }
    
    var p = new Person();
                                </pre>
                            </td>
                    </tr>
                </tbody>
            </table>
        </li>

    </ul>
    <h2>Expressions and operators</h2>
    <h3>operators</h3>
    <ul>
        <li>
            <caption>assignment operators赋值运算符</caption>
            <p>new things: Destructuring assignment</p>
            <p>used to unpack values from arrays, or properties from objects, into distinct values</p>
            <ul>
                <caption>advantages</caption>
                <li>it makes our code more readable</li>
                <li>performance, Destructuring encourages programmers to put object properties in local variables before using them</li>
            </ul>
            <h4>Arrary Destructuring</h4>
            <ol>
                <li>basic variable assignment(声明+赋值): var foo = ['one', 'two', 'three']; var [one, two, three] = foo;</li>
                <li>assignment seperate from declaration(声明和赋值分开): var a, b; [a, b] = [1, 2];</li>
                <li>Default values: var a, b;[a=5, b=7] = [1]; b的值时7否则是undefined</li>
                <li>swapping values: var a = 1; var b = 3; [a, b] = [b, a]; 不使用destructuring的话就需要使用一个临时变量</li>
                <li>ignore some values: var [a, , b] = [1,2,3] 使用逗号预留出空位</li>
                <li>assigning the rest of an array to a variable: var [a, ...b] = [1, 2, 3]; </li>
            </ol>
            <h4>Object Destructing</h4>
            <ol>
                <li>basic assignment:(声明+赋值) var o = {p: 42, q: true}; var {p, q} = o; </li>
                <li>assigment without declaration: (声明和赋值分开) var a,b; ({a, b} = {a: 1, b: 2}); <br>
                分开的情况下，必须在外边使用()，因为左边的{a,b}被识别成一个block而不是一个literal</li>
                <li>assgining to a new variable(使用新的变量名): var o = {p: 42, q: true}; var {p: foo, q: bar} = o;</li>
                <li>default values: var {a = 10, b = 5} = {a: 3};</li>
                <li>assigning to new varibales names and providing default values: var {a: aa = 10, b: bb = 5} = {a: 3};</li>
                <li>nested object and array destructuring: 分解时，遵守一一对应的原则，保证[]和{}对应进行赋值，<br>
                注意分解数组时候可以直接修改变量名，分解对象时修改变量名需要 old:new, 同时原变量名会直接释放 
                <pre>
let {name,habits:[first,,third],city:{current}} =  {
    name: "Tony",
    age: 18,
    job: "Developer",
    habits:["singing","programming","learning English"],
    city:{
        current: "Sydney",
        previous:"Shijian Zhuang"
    }
}
console.log(name)
console.log(first)
console.log(third)
console.log(current)
//Result:
// Tony
// singing
// learning English
// Sydney
                </pre>
            </li>
                <li>for of iteration and destructuring:</li>
                <li>unpacking fields from objects passed as function parameter</li>
                <li>rest in object Destructing</li>
                <li>combined Array and Object Destructuring</li>
            </ol>
        </li>
        <li>Comparison operators 比较运算符 (==,!=,===,!==,>,<,>=,<=) </li>
        <li>Arithmetic operators 算数运算符</li>
        <li>bitwise operators 位运算符</li>
        <li>Logical operators 逻辑运算符 (&&,||,!)</li>
        <li>String operators 字符串运算符(+)</li>
        <li>conditional(ternary) operators 条件运算符/三元运算符(?:)</li>
        <li>comma operations 逗号运算符()</li>
        <li>
            <caption>unary operators 一元运算符</caption>
            <ul>
                <li>delete: deletes an object, an object's property, or an element at a specified index in an array <br>
                只能删除没有显示申明的变量，例如 x =10，但是 var x =10不可以删除</li>
                <li>typeof: typeof (operand) 括号是可选的 返回一个string</li>
                <li>void: void(expression) https://www.quackit.com/javascript/tutorial/javascript_void_0.cfm</li>
            </ul>
        </li>
        <li>
            <caption>Relational operators 关系运算符</caption>
            <ul>
                <li>in： 检测对象是否有某个属性(等同于hasOwnProperty)  propNameOrNumber in objectName</li>
                <li>instanceof: 判断对象是不是指定类型 propNameOrNumber in objectName</li>
            </ul>
        </li>
    </ul>
    <h3>Expression</h3>
    <p>expression is any valid unit of code that resolves a value</p>
    <h2>Numbers and Dates</h2>
    <h2>Text formatting</h2>
    <h3 class="text-warning">String</h3>
    <p>string 和String对象是不同的. String Object is a wrapper around the string primitive data type</p>
    <p>但是我们可以使用任何string来调用String对象的方法，这是因为Javascript会自动将string字面值转化为String对象</p>
    <p>所以尽量使用string字面值，而不用使用String对象</p>
    <h3>Internationalization</h3>
    <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Text_formatting">check the link for more information</a>
    <h2>Regular expressions</h2>
    <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions">check the link for more information</a>
    <h2>indexed collections</h2>
    <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Indexed_collections">check the link for more information</a>
    <h2>keyed collections</h2>
<p></p>
    <h3>Maps</h3>
    <p>A map object is a simple key/value map and can iterate its elements in insertion order</p>
    <h4>advanages of Map over Object</h4>
    <ul>
        <li>keys of an object are Strings, where they can be of any type for a Map</li>
        <li>easy to get the size of a Map with map.size()</li>
        <li>the iteration of a map is in insertion order of the elements</li>
        <li>An Object has a prototype, so there are default keys in the map. (this can be bypassed using map = Object.create(null)).</li>
    </ul>
    <h3>Sets</h3>
    <p>A set is a collection of unique values</p>
    <p>conversion between Array and Set:  Array.from    [...mySet] = new Set([1,2,3])</p>
    <h4>advanages of Set over Array</h4>
    <ul>
        <li>Checking whether an element exists in a collection using indexOf for arrays is slow.</li>
        <li>Set objects let you delete elements by their value. With an array you would have to splice based on an element's index.</li>
        <li>The value NaN cannot be found with indexOf in an array.</li>
        <li>Set objects store unique values; you don't have to keep track of duplicates by yourself.</li>
    </ul>
    <h2>Object</h2>
    <ul>
        <li>access properties: objectName.propertyName</li>
        <li>Enumerate the properties of an object:
            <ul class="bg-warning">
                <li>for-in loop：This method traverses all enumerable properties of an object and its prototype chain</li>
                <li>Object.keys(o)：This method returns an array with all the own (not in the prototype chain) enumerable properties' names ("keys") of an object o</li>
                <li>Object.getOwnPropertyNames(o)：This method returns an array containing all own properties' names (enumerable or not) of an object o.</li>
            </ul>
        </li>
        <li>
            creating new objects <br>
            three ways:
            <ol>
                <li>using object initializer: <br>
                    obj 和 = 都是可选的，如果在其他的地方不需要使用这个object，可以省略
                    <pre>
var obj = { name:  'wujian', 
    age:  18,  
    run: function(){
        //注意如果没有return语句，只有console.log语句的话，在chrome dev tool里是不会有输出信息的
        console.log('he is so fast')
        return "he is so fat"
    } }; 
                    </pre>
                </li>
                <li>using a constructor function: <br>
                    there are two steps:
                    <ul>
                        <li>define the object type by writing a constructor function (good convention: capital initial letter) 
                            <pre>
function Car(make, model, year) {
    this.make = make;
    this.model = model;
    this.year = year;
    //注意使用的语法
    this.run = function(){
        console.log("it's fast")
        return "it's fast"
    };
    }
                            </pre>
                        </li>
                        <li>create an instance of the object with new
                            <pre>
var mycar = new Car('Eagle', 'Talon TSi', 1993);
                            </pre>
                        </li>
                        <br>
                    </ul>
                </li>
                <li>using the Object.create method</li>     
                <p>it's useful when you have already have a prototype object you want to create, 需要借助第一种创建方法</p>
                <p class="bg-warning">使用这种方法创建对象后，我尝试使用之前的三种方法查看属性，但是之后for-in的方法可以查到继承的属性</p>
                <pre>
// Animal properties and method encapsulation
var Animal = {
    type: 'Invertebrates', // Default value of properties
    displayType: function() {  // Method which will display type of Animal
    console.log(this.type);
    }
};

// Create new animal type called animal1 
var animal1 = Object.create(Animal);
animal1.displayType(); // Output:Invertebrates
                </pre>
            </ol>
        </li>
        <li>defining properties for an object type: object.prototype.propertyName = value</li>
        <li>defining setters and getters (two properties): <br>
            two ways:
            <ol>
                <li>defined by object initializer
                    <pre>
var o = {
    a: 7,
    get b() { return this.a + 1; },
    set c(x) { this.a = x / 2; }
    };
                    </pre>
                </li>
                <li>add later to any object at any time usign a getter or setter adding method
                    <pre>
var o = { a: 0 };

Object.defineProperties(o, {
    'b': { get: function() { return this.a + 1; } },
    'c': { set: function(x) { this.a = x / 2; } }
});                        
                    </pre>
                </li>
            </ol>
        </li>
    </ul>
    <h2 >details of the object model</h2>
    <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Details_of_the_Object_Model">check the link for more information</a>
    <h2>Using promises</h2>
    <p>A promise is an object representing the eventual completion or failture of asynchronous operation</p>
    <p>Essentially, a promise is a returned object to which you attach callbacks, instead of passing callbacks into a function.</p>
    <table class="table">
        <thead>
            <tr>
                <th>previous</th>
                <th>current</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>
                    <pre>
function successCallback(result) {
    console.log("Audio file ready at URL: " + result);
    }
    
    function failureCallback(error) {
    console.log("Error generating audio file: " + error);
    }
    
    createAudioFileAsync(audioSettings, successCallback, failureCallback);
                    </pre>
                </td>
                <td>
                    <pre>
const promise = createAudioFileAsync(audioSettings); 
promise.then(successCallback, failureCallback);
// the shorthand is below
createAudioFileAsync(audioSettings).then(successCallback, failureCallback);
                    </pre>
                </td>
            </tr>
        </tbody>
    </table>
    <ol>
        <p>advantages of Promise</p>
        <li>Guarantees
            <ul>
                <li>回调将在在当前js事件流完成后触发: callbacks will never be called before the completion of the current run of the Javascript event loop</li>
                <li>回调在异步调用之后触发: callbacks added with then even after the success or failure of the asynchronous call, will be called, as above</li>
                <li>多回调按顺序执行: Multiple callbacks may be added by calling then() several times. Each callback is executed one after another, in the order in which they were inserted.</li>
            </ul>
        </li>
        <li>Chaining</li>
        <p>then() function can create a new promise, different from the original one</p>
        <p>catch(failureCallback) is short for then(null,failureCallback).catch, which is useful to accomplish new actions even after an action failed in the chain</p>
        <p>important!!! Always return results, otherwise callbacks won't catch the result of a previous promise (with arrow functions () => x is short for () => { return x; }).</p>
        <li>Chaining after a catch</li>
        <li>Error propogation</li>
        <li>Promise rejection events</li>
        <li>Creating a Promise around an old callback API <br>
            A Promise can be created from scratch using its constructor. This should be needed only to wrap old APIs. <br>
            In an ideal world, all asynchronous functions would already return promises. Unfortunately, some APIs still 
            expect success and/or failure callbacks to be passed in the old way. The most obvious example is the setTimeout() function:
        </li>
    </ol>
    <h2>Iterators and generators</h2>
    <h3>iteration protocol: iterable protocol and iterator protocal</h3>
    <p>The iterable protocol allows JavaScript objects to define or customize their iteration behavior
        , such as what values are looped over in a for..of construct. Some built-in types are built-in iterables with a default iteration behavior, such as Array or Map, while other types (such as Object) are not. </p>
    <h3>Symbol</h3>
    <p>symbol is also a primitive value</p>
    <p>Symbol([description])  Description: Optional, string. A description of the symbol which can be used for debugging but not to access the symbol itself.</p>
    <h2>Meta programming</h2>
    <a href="#">详情后续</a>
    <h1>intermediate</h1>
    <h2>Introducing Javascript object</h2>
    <h3>Object Basics</h3>
    <p>查看之前的基础内容</p>
    <h3>Object-orientated Javascript for beginners</h3>
    <p>查看之前的基础内容</p>
    <h3>Object Prototype</h3>
    <p></p>
    <h3>Inheritance in Javascript</h3>
    <h3>JSON</h3>
    <p>JavaScript Object Notation (JSON) is a standard text-based format for representing structured data based on JavaScript object syntax. It is commonly used for transmitting data in web applications (e.g., sending some data from the server to the client, so it can be displayed on a web page, or vice versa).</p>
    <p> <b> JSON exists as a string</b> — useful when you want to transmit data across a network. It needs to be converted to a native JavaScript object when you want to access the data. This is not a big issue —  JavaScript provides a global JSON object that has methods available for converting between the two.</p>
    <p class="bg-warning">Note: Converting a string to a native object is called parsing, while converting a native object to a string so it can be transmitted across the network is called stringification.</p>
    <p>A JSON object can be stored in its own file, which is basically just a text file with an extension of .json, and a MIME type of application/json.</p>
    <h4>JSON structure</h4>
    <p>A JSON is a string whose format resembles very much JavaScript object literal format</p>
    <h4>Array as JSON</h4>
    <p>JSON is almost like a Javascript object, the reason is that <span class="text-danger">an array is also valid JSON</span> , for example</p>
    <pre>
            [
      {
        "name": "Molecule Man",
        "age": 29,
        "secretIdentity": "Dan Jukes",
        "powers": [
          "Radiation resistance",
          "Turning tiny",
          "Radiation blast"
        ]
      },
      {
        "name": "Madame Uppercut",
        "age": 39,
        "secretIdentity": "Jane Wilson",
        "powers": [
          "Million tonne punch",
          "Damage resistance",
          "Superhuman reflexes"
        ]
      }
    ]
    for example [0]["powers"][0].
    </pre>
    <h4>other userful notes</h4>
    <ul>
        <li>JSON is purely a data format — it contains only properties, no methods.</li>
        <li>JSON requires double quotes to be used around strings and property names. Single quotes are not valid. For object literal, it's not necessary</li>
        <li>Unlike in JavaScript code in which object properties may be unquoted, in JSON, only quoted strings may be used as properties. <br>
        对于JS对象来说，属性名可以不使用引号括起来，使用引号的话，可以使用单引号或者双引号，但是对于JSON来说，属性名必须用双引号</li>
    </ul>
    <h2>Client-side web APIs</h2>
    <h3>Introduction to web APIs</h3>
    <h4>what are APIs</h4>
    <p>Application Programming Interfaces (APIs) are constructs made available in programming languages to allow developers to create complex functionality more easily. They abstract more complex code away from you, providing some easier syntax to use in its place.</p>
    <h4>APIs in client-side Javascript</h4>
    <p>relationship between API, libraries and framework</p>
    <ul>
        <li>Third party APIs — constructs built into third-party platforms (e.g. Twitter, Facebook) that allow you to use some of those platform's functionality in your own web pages (for example, display your latest Tweets on your web page).</li>
        <li>JavaScript libraries — Usually one or more JavaScript files containing custom functions that you can attach to your web page to speed up or enable writing common functionality. Examples include jQuery, Mootools and React.</li>
        <li>JavaScript frameworks — The next step up from libraries, JavaScript frameworks (e.g. Angular and Ember) tend to be packages of HTML, CSS, JavaScript, and other technologies that you install and then use to write an entire web application from scratch. The key difference between a library and a framework is “Inversion of Control”. When calling a method from a library, the developer is in control. With a framework, the control is inverted: the framework calls the developer's code.</li>
    </ul>
    <h4>what can APIs do?</h4>
    <h5 class="bg-dark text-white">use of Common browse APIs</h5>
    <ul>
        <li>manipulating documents</li>
        <li>
            <caption>fetch data from the server</caption>
            <p>why do we need these APIs?</p>
            <p>Sometimes we need to update only part of the website, it's wasteful to load an entire page</p>
            <p>Loading some chunks of HTML, XML, JSON or plain text can be achieved by usign APIs like XMLHttpRequest or Fetch API</p>
            <ul>
                <li>
                    <b>XMLHttpRequest(often abbreviated to XHR)</b>
                    <p>You can retrieve data from a URL without having to do a full page refresh.</p>
                    <p>Despite its name, XMLHttpRequest can be used to retrieve any type of data, not just XML. It's because we often use this way to retrive XML data before</p>

                </li>
                <li>
                    <b>Fetch API</b>
                </li>
            </ul>
        </li>
        <li>drawing and manipulating graphics</li>
        <li>Audio and Video APIs</li>
        <li>Device APIs</li>
        <li>Client-side Storage</li>
    </ul>
    <h2>A re-introduction to JavaScript</h2>
    <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript">A good summary for quick review</a>
    <h2>JavaScript data structures</h2>
    <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures">quick review for data types</a>
    <h2>Equality comparison and sameness</h2>
    <ul>
        <li>double equals (==) will perform a type conversion when comparing two things, and will handle NaN, -0, and +0 specially to conform to IEEE 754 (so NaN != NaN, and -0 == +0);</li>
        <li>triple equals (===) will do the same comparison as double equals (including the special handling for NaN, -0, and +0) but without type conversion; if the types differ, false is returned.</li>
        <li>Object.is does no type conversion and no special handling for NaN, -0, and +0 (giving it the same behavior as === except on those special numeric values).</li>
    </ul>
    <h2>closure</h2>
    <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures">see details here</a>
    <p>Closures are useful because they let you associate some data (the lexical environment) with a function that operates on that data.</p>
    <p>This has obvious parallels to object-oriented programming, where objects allow us to associate some data (the object's properties) with one or more methods.</p> 
    <p>闭包是很有用的 因为它让我们可以将数据和函数联系起来，并且这个函数可以使用这些数据</p>
    <p>这和面向对象编程是非常相近的，面向对象编程就是把数据和一些方法联系起来, 通常情况下，这些数据就是对象的属性</p>
    <p>闭包的外部函数就好像是实例化了一个对象，创建了一个操作空间，提供了一个基本环境，即定义了对象的属性</p>
    <p>闭包的内部函数就和对象的方法相近，都是在对基本环境的数据进行操作，也能接受来自外部的参数</p>
    <h2>several keywords learning</h2>
    <h2>brower和node虽然都使用的是js，但是标准不同，在node中使用的是commonJS，在brower中使用的是ES(即ECMAscript)</h2>
    <h2>值得一提的是现在node中也可以使用ES标准</h2>
    <a href="https://www.jianshu.com/p/ce92a09ad6eb" target="_blank">如何在node中使用ES中的import和export</a>
    <table class="table" >
        <thead>
          <tr>
            <th scope="col"></th>
            <th scope="col" >Export</th>
            <th scope="col" >Import</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <th scope="row">Definition</th>
            <td>The export statement is used when creating JavaScript modules to export <span class="text-danger">functions, objects, or primitive values</span>  from the module so they can be used by other programs with the import statement.</td>
            <td>The static import statement is used to import features into JavaScript modules that have been exported by another module.</td>  
        </tr>
        <tr>
            <td colspan="3">To apply a module script to an HTML document, you need to use a &lt;script&gt; of type="module". The import statement cannot be used in non-module scripts </td>
        </tr>
          <tr>
            <th scope="row">individual features</th>
            <td>
                <pre>
export let name1, name2, …, nameN; // also var, const
export let name1 = …, name2 = …, …, nameN; // also var, const
export function functionName(){...}
export class ClassName {...}
e.g.
// export individual features (can export var, let,
// const, function, class)
export let myVariable = Math.sqrt(2);
export myFunction() { ... };
// export features declared earlier
export { myFunction, myVariable }; 
                </pre>
            </td>
            <td>
                <pre>
这里的{}不可以省略，否则会去查找该module的default
import { export } from "module-name";
e.g.
import {name} from "./test1.js"
                </pre>
            </td>
          </tr>
          <tr>
            <th scope="row">export list</th>
            <td>
                <pre>
export { name1, name2, …, nameN };
e.g.
//之前定义的变量，只需列出变量名并且加括号，如果是declaration和assignment在一起的话就不需要括号，只需要逗号连接
export{name,fn}
export let name ="wujian", fn = (a,b)=>{
    return a+b
};
                </pre>
            </td>
            <td>
                <pre>
import { export1 , export2 } from "module-name";
e.g.
import {name,fn} from "./test1.js"
                </pre>
            </td>
          </tr>
          <tr>
              <th scope="row">renaming</th>
              <td>
                  <pre>
export { variable1 as name1, variable2 as name2, …, nameN };
e.g.
let name ="wujian"
let fn = (a,b)=>{
    return a+b
}
export {name as name1, fn as fn1}
                  </pre>
              </td>
              <td>
                  <pre>
// Import renamed exports, 在export和import两端都可以进行重命名操作 
import { export as alias } from "module-name";
e.g.
import {name1 as name2,fn1 as fn2} from "./test1.js"
console.log(name2,fn2)
                  </pre>
              </td>
          </tr>
          <tr>
              <th scope="row">default(一般来说，设置成default是函数或者类，不会是基础类型)</th>
              <td>
                  <pre>
// export individual features as default
export default myFunction() { ... } 
export default class { .. }
// export feature declared earlier as default
export { myFunction as default };
e.g.
let fn = (a,b)=>{
    return a+b
}
export {fn as default}
//也可以将基础值作为默认值，但是不常用，这个时候可以省略var，let和const关键字
export default name = "tony";
                  </pre>
              </td>
              <td>
                  <pre>
// Import default export, 变量名可以随便取，import的时候不加括号就是引入default
import defaultExport from "module-name";
e.g.
import test1 from "./test1.js"
console.log(test1)
                  </pre>
              </td>
          </tr>
        </tbody>
      </table>
    <table class="table" >
        <thead>
          <tr>
            <th scope="col"></th>
            <th scope="col" >module exports/ exports</th>
            <th scope="col" >require</th>
          </tr>
        </thead>
        <tbody>
            <tr>
                <th scope="row">export literals</th>
                <td>
                    <pre>
//exports is an object, 给exports赋值，所以require可以直接获取值，可以是基本类型也可以是object
module.exports = 'Hello world';
//or
exports = 'Hello world';
                    </pre>
                </td>
                <td>
                    <pre>
var msg = require('./Messages.js');
console.log(msg);
                    </pre>
                </td>  
            </tr>
            <tr>
                <th scope="row">export object</th>
                <td>
                    <pre>
//exports是一个对象，所以也可以给他添加属性和方法，而不是直接赋予一个字面值
exports.SimpleMessage = 'Hello world';
//or
module.exports.SimpleMessage = 'Hello world';
                    </pre>
                </td>
                <td>
                    <pre>
var msg = require('./Messages.js');
console.log(msg.SimpleMessage);
                    </pre>
                </td>
            </tr>
            <tr>
                <th scope="row">export function(和export literal很相似，不过是作为一个方法使用)</th>
                <td>
                    <pre>
module.exports = function (msg) { 
    console.log(msg);
};
                    </pre>
                </td>
                <td>
                    <pre>
var msg = require('./Log.js');
msg('Hello World');
                    </pre>
                </td>
            </tr>
        </tbody>
    </table>
    <!-- Optional JavaScript -->
    <!-- jQuery first, then Popper.js, then Bootstrap JS -->
    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>

</body>
</html>